package com.dahai.common;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.WebUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 过滤器链配置
 */
public class SimpleRequetFilter implements Filter, InitializingBean, ApplicationContextAware, BeanNameAware {
    private ApplicationContext applicationContext;

    //过滤器
    private List<Filter> filterList = new ArrayList<Filter>();

    //excludeUri 不过滤的url
    private List<String > excludeUri;
    //过滤器的bean的名称
    private List<String> filterNames;

    public List<String> getExcludeUri() {
        return excludeUri;
    }

    public void setExcludeUri(List<String> excludeUri) {
        this.excludeUri = excludeUri;
    }

    public List<String> getFilterNames() {
        return filterNames;
    }

    public void setFilterNames(List<String> filterNames) {
        this.filterNames = filterNames;
    }

    private String name;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        if (!CollectionUtils.isEmpty(filterList)){
            for (Filter filter : filterList) {
                filter.init(filterConfig);
            }
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        try {

            //如果自定义的过滤器链为空
            if (CollectionUtils.isEmpty(filterList)){
                chain.doFilter(request, response);
                return;
            }else {
                //
                if (!excludes(request)){
                    VirtualFilterChain virtualFilterChain = new VirtualFilterChain(filterList, chain);
                    virtualFilterChain.doFilter(request, response);
                }else {
                    chain.doFilter(request, response);
                }
            }
        } finally {

        }

    }

    //判断是否排除

    private boolean excludes(ServletRequest request){

        if (!CollectionUtils.isEmpty(excludeUri)){
            HttpServletRequest request1 = (HttpServletRequest) request;
            String requestURI = request1.getRequestURI();
            for (String s : excludeUri) {
                if (s.contains(requestURI)){
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public void destroy() {

    }

    /**
     * 让bean 对 spring 知觉
     * @param name
     */
    @Override
    public void setBeanName(String name) {
        this.name = name;
    }

    //InitializingBean接口为bean提供了初始化方法的方式，它只包括afterPropertiesSet方法，凡是继承该接口的类，在初始化bean的时候都会执行该方法。
    @Override
    public void afterPropertiesSet() throws Exception {
        //拦截器list
        for (String filterName : filterNames) {
            //不能配置当前过滤器,避免产生死循环
            if (filterName.equals(name)){
                throw new RuntimeException("不能配置当前的Filter,避免产生死循环");
            }
            Filter filter = (Filter)applicationContext.getBean(filterName);
            filterList.add(filter);
        }
    }

    //提供application
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }


    public static class VirtualFilterChain  implements FilterChain{
        //过滤器list
        private List<Filter> filterList;
        //当前责任链index
        private int currentIndex = 0;
        //责任链
        private FilterChain chain;

        public VirtualFilterChain(List<Filter> filterList, FilterChain chain) {
            this.filterList = filterList;
            this.chain = chain;
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {

            if (currentIndex == filterList.size()){
                chain.doFilter(request, response);
            }else {
                currentIndex++;
                Filter filter = filterList.get(currentIndex-1);
                filter.doFilter(request, response, this);

            }
        }
    }


}
